package com.tensai.other.zd.screen;

import cn.hutool.core.util.RuntimeUtil;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
//import com.sun.jna.platform.win32.Dwmapi;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.StdCallLibrary;
import lombok.extern.slf4j.Slf4j;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;

@Slf4j
public class SwitchScreen1 {
    public interface User32 extends StdCallLibrary {
        User32 INSTANCE = Native.load("user32", User32.class);

        boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);

        int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);

        boolean SetForegroundWindow(HWND hWnd);

        boolean ShowWindow(HWND hWnd, int nCmdShow);

        boolean AllowSetForegroundWindow(WinDef.DWORD dword);
    }

    public static void main(String[] args) {
        init();
        // ---------------------
        setFrontBrowser(args[0]);
    }

    public static void init() {
        //TODO 修改为自己的bat文件
        RuntimeUtil.execForStr("start aaa.bat");
        Set<String> set = new HashSet<String>() {{
            add("OPLPage");
            add("SPLPage");
        }};
        Timer timer = new Timer();
        AtomicInteger count = new AtomicInteger(0);
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                Map<String, HWND> map = getHandler(set);
                if (map.keySet().size() == 2) {
                    setFrontBrowser("OPLPage");
                    this.cancel();
                } else {
                    if (count.incrementAndGet() > 10) {
                        this.cancel();
                        timer.cancel();
                    } else {
                        log.info("初始化任务执行中 {}", count.get());
                    }

                }
            }
        }, 0, 1000);
    }

    private static void setFrontBrowser(String browserName) {
        HWND hwnd = getHandler(browserName);
        boolean a = User32.INSTANCE.ShowWindow(hwnd, 1);
        boolean b = User32.INSTANCE.AllowSetForegroundWindow(new WinDef.DWORD(-1));
//        Dwmapi.INSTANCE.DwmSetWindowAttribute(hwnd, Dwmapi.DWMWA_DISALLOW_PEEK, true);
        boolean c = User32.INSTANCE.SetForegroundWindow(hwnd);
        log.info("设置前景浏览器 {} - {} - {} - {}", browserName, a, b, c);
    }

    private static HWND getHandler(String title) {
        AtomicReference<HWND> hwnd0 = new AtomicReference<>();
        user32Dll(getHwndBySTitle(), Tuples.of(title, hwnd0));
        return hwnd0.get();
    }

    private static Map<String, HWND> getHandler(Set<String> set) {
        Map<String, HWND> map = new HashMap<>();
        user32Dll(getHwndMapBySet(), Tuples.of(set, map));
        return map;
    }

    private static <T> void user32Dll(BiConsumer<T, Tuple2<String, HWND>> consumer, T t) {
        User32.INSTANCE.EnumWindows((hwnd, pointer) -> {
            byte[] windowText = new byte[512];
            User32.INSTANCE.GetWindowTextA(hwnd, windowText, 512);
            String wText = Native.toString(windowText);
            consumer.accept(t, Tuples.of(wText, hwnd));
            return true;
        }, null);
    }

    private static BiConsumer<Tuple2<String, AtomicReference<HWND>>, Tuple2<String, HWND>> getHwndBySTitle() {
        return (tp21, tp22) -> {
            if (!tp22.getT1().isEmpty() && tp22.getT1().contains(tp21.getT1())) {
                log.info("捕捉到浏览器 {}", tp21.getT1());
                tp21.getT2().set(tp22.getT2());
            } else {
                log.trace("过滤掉的进程 {}", tp22.getT1());
            }
        };
    }

    private static BiConsumer<Tuple2<Set<String>, Map<String, HWND>>, Tuple2<String, HWND>> getHwndMapBySet() {
        return (tp21, tp22) -> {
            if (!tp22.getT1().isEmpty()) {
                tp21.getT1().forEach(it -> {
                    if (tp22.getT1().contains(it)) {
                        tp21.getT2().put(it, tp22.getT2());
                        log.info("获取到进程 - {}", tp22.getT1());
                    }
                });
            }
        };
    }


}
